package tum0r.webengine.main

import sun.misc.Unsafe
import tum0r.webengine.config.ApplicationConfig
import tum0r.webengine.config.DatabaseConfig
import tum0r.webengine.config.LogFileConfig
import tum0r.webengine.core.handle.AfterResponse
import tum0r.webengine.core.handle.Filter
import tum0r.webengine.extension.check
import tum0r.webengine.extension.errorLog
import tum0r.webengine.extension.infoLog
import tum0r.webengine.models.database.DatabaseConnect
import java.io.File
import java.lang.reflect.Field

/**
 * 说明: 框架配置
 *
 * 创建者: tum0r
 *
 * 时间: 2021/11/8 12:18
 */
class Setting {
    companion object {
        // region 日志设置

        /**
         * 设置日志文件
         */
        @JvmStatic
        fun setLogFile(index: Int, file: File, logFiles: Array<File?>, type: String) {
            if (index in 0 until LogFileConfig.LOG_FILE_COUNT) {
                logFiles[index] = file
                "[${
                    when (index) {
                        1 -> "DEBUG"
                        2 -> "ERROR"
                        else -> "INFO"
                    }
                }]${type}设置为[${file.absolutePath}]".infoLog()
            } else
                "${type}文件类型数为[${LogFileConfig.LOG_FILE_COUNT}]".errorLog()
        }

        /**
         * 设置日志文件
         *
         * @param[index] 日志文件类型
         * @param[file] 日志文件
         */
        @JvmStatic
        fun setLogFile(index: Int, file: File) = setLogFile(index, file, LogFileConfig.LOG_FILES, "日志")

        /**
         * 设置日志文件
         *
         * @param[index] 日志文件类型
         * @param[path] 日志文件路径
         */
        @JvmStatic
        fun setLogFile(index: Int, path: String) {
            if (path.check("日志文件路径")) setLogFile(index, File(path))
        }

        /**
         * 设置日志文件
         *
         * @param[index] 日志文件类型
         * @param[file] 日志文件
         */
        @JvmStatic
        fun setOldLogFile(index: Int, file: File) = setLogFile(index, file, LogFileConfig.OLD_LOG_FILES, "旧日志")

        /**
         * 设置日志文件
         *
         * @param[index] 日志文件类型
         * @param[path] 日志文件路径
         */
        @JvmStatic
        fun setOldLogFile(index: Int, path: String) {
            if (path.check("旧日志文件路径")) setLogFile(index, File(path))
        }

        // endregion

        // region 扫描包设置

        /**
         * 检查设置的包名是否合法
         *
         * @param[packageName] 包名
         * @param[name] 包类型名
         */
        @JvmStatic
        fun checkScanPackage(packageName: String, name: String): String? {
            banLogFile()
            if (!packageName.check("扫描${name}的包路径")) return null
            "扫描${name}的包名设置为[$packageName]".infoLog()
            return packageName
        }

        /**
         * 设置扫描接口的包名
         *
         * @param[packageName] 包名
         */
        @JvmStatic
        fun setScanServersPackage(packageName: String) {
            ApplicationConfig.SCAN_SERVERS_PACKAGE = checkScanPackage(packageName, "接口") ?: ApplicationConfig.SCAN_SERVERS_PACKAGE
        }

        /**
         * 设置扫描命令的包名
         *
         * @param[packageName] 包名
         */
        @JvmStatic
        fun setScanCommandsPackage(packageName: String) {
            ApplicationConfig.SCAN_COMMANDS_PACKAGE = checkScanPackage(packageName, "命令") ?: ApplicationConfig.SCAN_COMMANDS_PACKAGE
        }

        /**
         * 设置扫描数据库表的包名
         *
         * @param[packageName] 包名
         */
        @JvmStatic
        fun setScanTablesPackage(packageName: String) {
            ApplicationConfig.SCAN_TABLES_PACKAGE = checkScanPackage(packageName, "数据库表") ?: ApplicationConfig.SCAN_TABLES_PACKAGE
        }

        // endregion

        /**
         * 添加请求过滤规则
         *
         * @param[filter] 过滤规则
         */
        @JvmStatic
        fun addFilter(filter: Filter) {
            if (ApplicationConfig.FILTERS.add(filter)) "添加过滤规则[${filter.filterName.ifBlank { "过滤规则${ApplicationConfig.FILTERS.size}" }}]".infoLog()
        }

        /**
         * 添加响应完请求后要进行的处理
         *
         * @param[afterResponse] 要进行的处理
         */
        @JvmStatic
        fun addAfterResponse(afterResponse: AfterResponse) {
            afterResponse.name = afterResponse.name.ifBlank { "未命名${ApplicationConfig.AFTER_RESPONSE}" }
            if (ApplicationConfig.AFTER_RESPONSE.add(afterResponse)) "添加响应请求后的处理[${afterResponse.name}]".infoLog()
        }

        /**
         * 添加数据库信息
         *
         * @param[info] 数据库连接信息
         */
        @JvmStatic
        fun addDatabaseInfo(info: DatabaseConnect) {
            for (item in DatabaseConfig.DATABASE_CONNECT_INFO) if (item.name == info.name) "已存在名称为[${item.name}]的连接".errorLog(true)
            DatabaseConfig.DATABASE_CONNECT_INFO.add(info)
        }

        /**
         * 修改网站图标
         *
         * @param[index] 0 Safari浏览器 1 其他浏览器
         * @param[file] 网站图标文件，为null恢复默认
         * @param[mapping] 网站图标映射路径
         */
        @JvmStatic
        fun changeIcon(index: Int, file: File?, mapping: String) {
            if (index !in 0 until ApplicationConfig.ICONS.size) {
                "网站图标下标错误".errorLog()
                return
            }
            if (mapping.check("网站图标映射路径")) return
            ApplicationConfig.ICONS[index].iconFile = file
            ApplicationConfig.ICONS[index].mapping = mapping
            "网站图标文件设置为[${if (file != null) file.absolutePath else "默认图标"}]".infoLog()
            "网站图标映射路径设置为[${mapping}]".infoLog()
        }

        /**
         * 不显示"An illegal reflective access operation has occurred"警告信息
         */
        @JvmStatic
        fun disableWarning() {
            try {
                val theUnsafe: Field = Unsafe::class.java.getDeclaredField("theUnsafe")
                theUnsafe.isAccessible = true
                val u: Unsafe = theUnsafe.get(null) as Unsafe
                val cls = Class.forName("jdk.internal.module.IllegalAccessLogger")
                val logger: Field = cls.getDeclaredField("logger")
                u.putObjectVolatile(cls, u.staticFieldOffset(logger), null)
            } catch (ignore: Exception) {
            }
        }
    }
}